package cn.ym.aircraft;

import javax.swing.JPanel;
import javax.swing.JFrame;
import java.awt.Graphics;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Arrays;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;


public class World extends JPanel {
    protected static final int WIDTH = 400;
    protected static final int HEIGHT = 700;
    protected Hero hero = new Hero();
    protected Sky sky = new Sky();
    protected FlyingObject[] enemies = {};
    protected Bullet[] bullets = {};

    protected static final int START = 0;
    protected static final int RUNNING = 1;
    protected static final int PAUSE = 2;
    protected static final int GAME_OVER = 3;
    protected int state = START;

    public void initial() {
        this.score = 0;
        this.hero = new Hero();
        this.sky = new Sky();
        this.enemies = new FlyingObject[0];
        this.bullets = new Bullet[0];
    }

    public void paint(Graphics g) {
        sky.paintImage(g);
        hero.paintImage(g);
        for (FlyingObject object :
                enemies) {
            object.paintImage(g);
        }
        for (Bullet bullet :
                bullets) {
            bullet.paintImage(g);
        }

        g.drawString("SCORE:" + this.score, 30, 20);
        g.drawString("LIFE:" + hero.getLife(), WIDTH - 90, 20);
        g.drawString("FIRE:" + hero.getFire(), 30, HEIGHT - 50);

        switch (state) {
            case START:
                g.drawImage(Images.start, 0, 0, null);
                break;
            case PAUSE:
                g.drawImage(Images.pause, 0, 0, null);
                break;
            case GAME_OVER:
                g.drawImage(Images.gameover, 0, 0, null);
                break;
        }

    }

    public static void main(String[] args) {
        JFrame frame = new JFrame();
        World world = new World();
        frame.add(world);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(WIDTH, HEIGHT);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);

        world.action();
    }

    public void action() {

        MouseAdapter m = new MouseAdapter() {
            @Override
            public void mouseMoved(MouseEvent e) {
                if (state == RUNNING) {
                    hero.moveTo(e.getX(), e.getY());
                }
            }

            @Override
            public void mouseClicked(MouseEvent e) {
                switch (state) {
                    case START:
                        state = RUNNING;
                        break;
                    case GAME_OVER:
                        initial();
                        state = START;
                        break;
                }
            }
            @Override
            public void mouseExited(MouseEvent e) {
                if (state == RUNNING){
                    state = PAUSE;
                }
            }
            @Override
            public void mouseEntered(MouseEvent e) {
                if (state == PAUSE){
                    state = RUNNING;
                }
            }
        };
        this.addMouseListener(m);
        this.addMouseMotionListener(m);

        Timer timer = new Timer();
        int interval = 10;
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                if (state == RUNNING) {
                    enemiesEnterAction();
                    bulletEnterAction();
                    stepAction();
                    removeOutOfBound();
                    bulletBangAction();
                    heroBangAction();
                    checkGameOver();
                }
                repaint();
            }
        }, interval, interval);
    }

    public void checkGameOver() {
        if (hero.getLife() <= 0) {
            hero.goDead();
            state = GAME_OVER;
        }
    }

    public void heroBangAction() {
        for (FlyingObject object :
                enemies) {
            if (hero.isLive() && object.isLive() && object.isHit(hero)) {
                object.goDead();
                hero.subtractLife();
                hero.clearFire();
            }
        }
    }

    private int score = 0;

    /**
     * 射击与奖励
     */
    public void bulletBangAction() {
        for (Bullet bullet :
                bullets) {
            for (FlyingObject object :
                    enemies) {
                if (bullet.isLive() && object.isLive() && bullet.isHit(object)) {
                    bullet.goDead();
                    object.goDead();
                    if (object instanceof AwardType) {
                        AwardType obj = (AwardType) object;
                        if (AwardType.LIFE == obj.getAwardType()) {
                            if (object instanceof EnemyLife) {
                                hero.addLife((((EnemyLife) object).getLife()));//生命奖励
                            }
                        }
                        if (AwardType.FIRE == obj.getAwardType()) {
                            if (object instanceof EnemyFire) {
                                hero.addFire((((EnemyFire) object).getFire()));//火力奖励
                            }
                        }
                    }
                    if (object instanceof EnemyScore && !(object instanceof AwardType)) {
                        score += ((EnemyScore) object).getScore();
                    }

                    if (object instanceof EnemyLife && !(object instanceof AwardType)) {
                        hero.addLife(((EnemyLife) object).getLife());
                    }
                }
            }
        }
    }

    /**
     * 删除越界对象，防止内存泄漏
     */
    public void removeOutOfBound() {
        for (int i = 0; i < enemies.length; i++) {
            if (enemies[i].isOutOfBound() || enemies[i].isRemove()) {
                enemies[i] = enemies[enemies.length - 1];
                enemies = Arrays.copyOf(enemies, enemies.length - 1);
            }
        }
        for (int i = 0; i < bullets.length; i++) {
            if (bullets[i].isOutOfBound() || bullets[i].isRemove()) {
                bullets[i] = bullets[bullets.length - 1];
                bullets = Arrays.copyOf(bullets, bullets.length - 1);
            }
        }
    }

    private int bulletActionIndex = 0;

    /**
     * 发射子弹间隔50毫秒
     */
    public void bulletEnterAction() {
        bulletActionIndex++;
        if (bulletActionIndex % 20 == 0) {
            Bullet[] bullet = this.hero.shoot();
            bullets = Arrays.copyOf(bullets, bullets.length + bullet.length);
            System.arraycopy(bullet, 0, bullets, bullets.length - bullet.length, bullet.length);
        }
    }

    public void stepAction() {
        sky.step();
        for (FlyingObject enemie :
                enemies) {
            enemie.step();
        }
        for (Bullet bullet :
                bullets) {
            bullet.step();
        }
    }

    private int enemiesEnterIndex = 0;

    public void enemiesEnterAction() {
        enemiesEnterIndex++;
        if (enemiesEnterIndex % 30 == 0) {
            FlyingObject obj = nextEnemies();
            enemies = Arrays.copyOf(enemies, enemies.length + 1);
            enemies[enemies.length - 1] = obj;
        }
    }

    private int type = 5;

    public FlyingObject nextEnemies() {
        Random rand = new Random();
        int newType = rand.nextInt(type) + 1;
        if (newType == type) {
            return new Bee();
        } else if (newType < type / 2) {
            return new Airplane();
        } else {
            return new BigAirplane();
        }
    }
}
